package com.zlyx.easy.socket;

import org.springframework.context.ApplicationContext;

import com.zlyx.easy.core.loggers.Logger;
import com.zlyx.easy.core.map.EasyMap;
import com.zlyx.easy.core.map.Maps;
import com.zlyx.easy.core.reflect.ProxyUtils;
import com.zlyx.easy.core.refresh.IHandlerOnChanged;
import com.zlyx.easy.core.refresh.IHandlerOnRefreshed;
import com.zlyx.easy.core.refresh.annotations.RefreshBean;
import com.zlyx.easy.core.spring.RepeatedBean;
import com.zlyx.easy.core.utils.ObjectUtils;
import com.zlyx.easy.core.utils.ThreadUtils;
import com.zlyx.easy.socket.annotations.SocketHandler;
import com.zlyx.easy.socket.core.AioTcpMsgHandlerFactory;
import com.zlyx.easy.socket.core.BioTcpMsgHandlerFactory;
import com.zlyx.easy.socket.core.BioUdpMsgHandlerFactory;
import com.zlyx.easy.socket.core.NioTcpMsgHandlerFactory;
import com.zlyx.easy.socket.core.NioUdpMsgHandlerFactory;
import com.zlyx.easy.socket.core.supports.AbstractMsgHandlerFactory;
import com.zlyx.easy.socket.interfaces.IMsgHandler;

/**
 * @Auth 赵光
 * @Describle
 * @2018年12月22日 下午4:41:07
 */
@SuppressWarnings("rawtypes")
@RefreshBean(todo = { "Socket连接管理平台" })
public class MsgFactoryHandlerManager extends RepeatedBean<IMsgHandler>
		implements IHandlerOnRefreshed, IHandlerOnChanged {

	private EasyMap<String, AbstractMsgHandlerFactory> factorys = Maps.newMap();

	@Override
	public void doOnChanged(ApplicationContext context) throws Exception {
		for (String factoryName : factorys.keySet()) {
			factorys.get(factoryName).closeServer();
		}
		Logger.info("Easy-socket have been closed!");
	}

	@Override
	public void doOnRefreshed(ApplicationContext applicationContext) {
		try {
			if (ObjectUtils.isNotEmpty(beans)) {
				AbstractMsgHandlerFactory factory = null;
				SocketHandler msgHandler = null;
				for (IMsgHandler handler : beans) {
					if (handler.isOpen()) {
						msgHandler = ProxyUtils.getTarget(handler).getClass().getAnnotation(SocketHandler.class);
						factory = getFactory(handler, msgHandler);
						if (factory != null) {
							factorys.put(ObjectUtils.className(handler), factory);
							ThreadUtils.execute(factory);
							Logger.info("Easy-socket have started an " + msgHandler.type() + " listener on port "
									+ msgHandler.port() + " for " + ObjectUtils.className(handler));
						}
					}
				}
			}
			Logger.info("Easy-socket have been started!");
		} catch (Exception e) {
			Logger.err(e);
		}
	}

	private AbstractMsgHandlerFactory getFactory(IMsgHandler<?> handler, SocketHandler msgHandler) throws Exception {
		AbstractMsgHandlerFactory factory = null;
		if (msgHandler.isOpen()) {
			int port = msgHandler.port();
			float size = msgHandler.size();
			switch (msgHandler.type()) {
			case BTM: {
				factory = new BioTcpMsgHandlerFactory(port, size, handler);
				break;
			}
			case NTM: {
				factory = new NioTcpMsgHandlerFactory(port, size, handler);
				break;
			}
			case ATM: {
				factory = new AioTcpMsgHandlerFactory(port, size, handler);
				break;
			}
			case BUM: {
				factory = new BioUdpMsgHandlerFactory(port, size, handler);
				break;
			}
			case NUM: {
				factory = new NioUdpMsgHandlerFactory(port, size, handler);
				break;
			}
			}
		}
		return factory;
	}
}
